home *** CD-ROM | disk | FTP | other *** search
/ Light ROM 3 / Light ROM 3 - Disc 2.iso / programs / amiga / imagefx / imagekit / imagekit.lha / ImageFX_SDK / doc / Modules.doc < prev    next >
Text File  |  1992-12-16  |  28KB  |  673 lines

  1.  
  2.  
  3.  
  4.  
  5.                                EXPANDING IMAGEFX
  6.  
  7.                             Developer Documentation
  8.                     for the ImageFX Image Processing System
  9.                                by Thomas Krehbiel
  10.  
  11.  
  12.  
  13. WARNING:   This  document  assumes that you are familiar with programming on the
  14. Amiga,  especially  in  the 'C' language.  It also assumes that you are at least
  15. somewhat familiar with the ImageFX program itself.
  16.  
  17.  
  18.  
  19.  
  20.  
  21.                                   0. CONTENTS
  22.  
  23. 0. Contents
  24. 1. Introduction
  25. 2. Basics
  26.      2.1. Compiling Conventions
  27.      2.2. ScanBase
  28. 3. Modules
  29.      3.1.  Theory
  30.      3.2.  Standard Module Startup Code
  31.      3.3.  Module Caveats
  32.      3.4.  Types of Modules
  33.           3.2.1.  Loader
  34.           3.2.2.  Saver
  35.           3.2.3.  Render
  36.           3.2.4.  Scanner
  37.           3.2.5.  Printer
  38.           3.2.6.  Preview
  39.      3.5.  Language
  40.      3.6.  Preferences
  41.      3.7.  Modules and Arexx
  42. 4. Hooks
  43.      4.1.  Theory
  44.      4.2.  Hook Construction
  45.      4.3.  Language
  46.      4.4.  Hooks and Arexx
  47.  
  48.  
  49.  
  50.  
  51.  
  52.                                 1. INTRODUCTION
  53.  
  54.  
  55.      ImageFX  was  designed  to  be  expandable  by  anyone  with an inclination
  56. towards  programming,  through  the  use of Modules and Hooks.  What are Modules
  57. and Hooks you ask?  Well, sit back and I'll explain:
  58.  
  59.      A  "Module" is like an Amiga shared library.  ImageFX loads the module into
  60. memory  and  calls functions in it to get things done.  Every effort was made to
  61. make  "black  boxes"  of  these  modules,  thus it is possible to update or even
  62. replace  modules  without  bothering  ImageFX.   Modules  are  broken  down into
  63. several  types,  each  one  designed to do a specific thing.  They are:  Loader,
  64. Saver,  Preview,  Scanner,  Render, Printer, Quantize, and Dither modules.  Each
  65. module type is explained in more detail below.
  66.  
  67.      A  "Hook"  is  a  more  free-form  type  of  expansion  for ImageFX.  It is
  68. essentially  just  a program that is able to access much of the internal "stuff"
  69. of  ImageFX,  including  image buffers and the like.  ImageFX launches the Hook,
  70. waits  for  it  to  complete,  and  then  continues  as normal.  Thus a Hook has
  71. virtually  unlimited  application,  ranging from adding simple effects to adding
  72. whole new interfaces to the program.
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.                                    2. BASICS
  81.  
  82.      This  section describes some things you should know that are common to both
  83. the Modules and Hooks.
  84.  
  85.  
  86. 2.1. Compiling Conventions
  87.  
  88.      This  document  assumes you are using the SAS/C compiler.  All examples and
  89. code  were compiled with SAS/C 5.10b, and all object modules provided are in the
  90. standard  Amiga  link  library  format.   They  may require some modification to
  91. compile under other systems (especially Aztec).
  92.  
  93.      32-bit int's are assumed throughout this document.
  94.  
  95.      All  example  source  code  assumes  you are using at least the V37 include
  96. files.   If  you don't have them, I strongly suggest you get them along with the
  97. 2.0  enhancer  kit.  The sooner we stamp out 1.3, the better off we'll all be...
  98. :)
  99.  
  100. 2.2. ScanBase
  101.  
  102.      When  ImageFX  is  loaded,  it  creates  a  shared library in memory.  This
  103. library  contains  a plethora of useful functions for dealing with ImageFX.  The
  104. library  structure  (struct  ScanBase)  itself  also  contains  a  lot of useful
  105. information,  like  Screen  pointers, drawing mode state information, and things
  106. like that.  For details on the functions, consult the appropriate autodoc file.
  107.  
  108.      Since  more  than  one  ImageFX  may  be  running  at once, the name of the
  109. library  has  to also be different for each copy of the program.  The convention
  110. used  is  as  follows:   For  the  first  copy of ImageFX loaded, the library is
  111. called  "scan1.library";  for  the second copy of ImageFX, the library is called
  112. "scan2.library"; and so on.
  113.  
  114.      Normally,  you  will not need to worry about opening the library yourself. 
  115. Modules  are passed a pointer to ScanBase which they can use directly.  Standard
  116. initialization  code  provided  for writing Hooks also takes care of getting the
  117. right  ScanBase pointer.  You generally only need to know that there is a global
  118. ScanBase  pointer  available,  and  thus  all  the functions of that library are
  119. available.
  120.  
  121.      The  library  function calls are all registerized, so it should be possible
  122. to  call  scan.library from just about any language.  The developer distribution
  123. uses  pragmas  for  the  library  calls, so you may need to adjust this for your
  124. particular  setup.   An  FD  file  is  included  so  you can build your own stub
  125. library if necessary.
  126.  
  127.      A link-time library ("scan.lib") is included which contains varargs
  128. versions of some of the functions in scan.library, as well as few other handy
  129. functions not included in scan.library.
  130.  
  131.  
  132.  
  133.  
  134.                                    3. MODULES
  135.  
  136. 3.1. Theory
  137.  
  138.      ImageFX  Modules  are  strongly  based on Amiga shared libraries.  They are
  139. built  in  almost  exactly  the  same  way.   If you aren't familiar with how to
  140. create  a  shared library, I strongly suggest that you review the subject (check
  141. the RKMs) before delving into this.
  142.  
  143.      A  Module  has  the 4 standard library vectors of OPEN, CLOSE, EXPUNGE, and
  144. RESERVED.   In  addition,  each type of module has additional vectors which must
  145. be provided (see individual descriptions below).
  146.  
  147.      Each   Module   has   a   ModuleBase  structure  associated  with  it  (see
  148. "scan/mod.h"),  which  is  based  on  the  standard Exec Library structure.  The
  149. ModuleBase  structure  is  allocated  by ImageFX and passed to the Module's OPEN
  150. vector,  where  the  Module's  job is to fill in the fields of the structure and
  151. return  it.  This  is  also  where  the  module  does any pre-use initialization
  152. required   (such   as  opening  libraries,  etc.).   By  "pre-use"  I  mean  any
  153. initialization  that  will cause the Module open to fail if something goes wrong
  154. (for  example,  if a module depends on some kind of hardware and the hardware is
  155. not  found).   For  most  modules  there is another function to do less critical
  156. initializations such as initializing variables and such.
  157.  
  158.      ImageFX  will  fill  in  a  few  fields  in the ModuleBase structure before
  159. passing  it to the Module, most notably the SysLib and ScanBase pointers.  These
  160. may   be   copied   to   the  Module's  global  SysBase  and  ScanBase  pointers
  161. respectively,  to  give  access  to  those  libraries.   ScanBase  also contains
  162. pointers to IntuitionBase and GfxBase, so those may also be copied if needed.
  163.  
  164.      Some  of the common fields of ModuleBase that the Module OPEN vector should
  165. fill in are described below:
  166.  
  167.      NewGad:   Points  to an array of NewGad structures, which describes the GUI
  168. (gadgets, text, etc.) for this module (if it has one).
  169.  
  170.      Language:   A  string  representing  the  "tag" to look for to find all the
  171. text  associated with this module.  A NULL indicates this module has no text, or
  172. you're  not bothering with internationalizing the module.  See the section below
  173. on internationalizing ImageFX modules.
  174.  
  175.      LangCount:  The total number of text strings to look for.
  176.  
  177.      CmdTable:   Pointer  to  an  array of RXCMD structures, which describes the
  178. Arexx  commands  that  this module understands.  Loaders and Savers only use the
  179. first entry.  If NULL, this module has no Arexx commands.
  180.  
  181.      PrefID:   Four-byte  ID "tag" used to locate and store preferences settings
  182. for  this  module.   Each module MUST have a unique 4-byte ID, or disaster could
  183. result  (or  at  least mixed-up preferences settings).  If 0, this module has no
  184. preferences.
  185.  
  186.      PrefLen:   Length  of  the structure that contains the module's preferences
  187. settings.   ImageFX  will  ask  the  module to fill in a structure of this size,
  188. which  it will then write to disk when the user wants to Save Prefs.  Similarly,
  189. when  the  user  Loads  Prefs, a structure of this size which has been read from
  190. disk will be presented to the module.
  191.  
  192.  
  193.  
  194.  
  195.  
  196.      NewWin:   Pointer  to a NewWindow structure.  Only used for Preview modules
  197. so  that  ImageFX can open the Preview Options window.  May be NULL if there are
  198. no preview options.
  199.  
  200.      All  other  fields  of  the  ModuleBase  structure  should  be  considered read
  201. only.  Tampering with them may be dangerous.
  202.  
  203.  
  204. 3.2. Standard Module Startup Code
  205.  
  206.      I  have  provided  a  link-time  module which does 99% of the grunt work of
  207. creating  a  module.   You need only provide a function table, the name and type
  208. of  your  module, and special initialization and cleanup functions.  The library
  209. does the rest.
  210.  
  211.      This  wonderous  achievement  is  called  "lib.o",  and should be the first
  212. module in your link list.
  213.  
  214.      Here are the things you need to specify:
  215.  
  216.      LibraryID:   A  pointer to a string which gives pertinant information about
  217. your module.  It should be in the form of a standard 2.0 version string:
  218.  
  219.                     "$VER: name version.revision (dd.mm.yy)"
  220.  
  221.      LibraryType:   A byte indicating the type of module this is.  Should be one
  222. of the NT_* constants defined in "scan/mod.h".
  223.  
  224.      FuncTable:   A  LONG array, where each element is a pointer to a function. 
  225. This  is the library vector table, and the first four functions should always be
  226. LibOpen,  LibClose,  LibExpunge,  and  LibNull (they are defined in lib.o).  The
  227. remaining  functions  depend  on  the  type of module (see below).  The function
  228. table must be terminated with a -1 entry.
  229.  
  230.      UserOpen:   Initialization function called within the OPEN vector.  This is
  231. where  you  should  take  the  time  to initialize the appropriate fields of the
  232. ModuleBase  structure,  which  is passed to you in A6 (a good place to use SAS's
  233. __asm  register  parameters).   The  ModuleBase  parameter is also placed on the
  234. stack.
  235.  
  236.      UserClose:   Cleanup  function called within the CLOSE vector.  This should
  237. cleanup  anything  that  you (and only you) allocated in the UserOpen() function
  238. above.   This  is  also  passed  a pointer to struct ModuleBase in A6 and on the
  239. stack.
  240.  
  241.      The  startup  code  will  fill  in  the  SysBase,  ScanBase, IntuitionBase,
  242. GfxBase,  and  ModuleBase  (pointing  to  the module's own ModuleBase structure)
  243. global pointers.
  244.  
  245.  
  246. 3.3. Module Caveats
  247.  
  248.      Generally  the same things that are not possible in an Amiga shared library
  249. are  not  possible  in  a Module.  Most notably, you cannot use any of the stdio
  250. functions.   Fortunately,  however, there are similar buffered file I/O routines
  251. provided in ScanBase (see Scan.autodoc for details).
  252.  
  253.      While  it  is  possible  to  use  floating point math, you can only use the
  254.  
  255.  
  256.  
  257.  
  258. inline  FPU math (-f8/lcm881) or the SAS floating point (-fl/lcm) routines.  You
  259. may  NOT  use  either  of  the  Amiga  floating  point libraries (-fi/lcmieee or
  260. -ff/lcmffp)  for reasons better left unsaid.  For obvious reasons, I'd recommend
  261. staying   away  from  the  floating  point  altogether  unless  it's  absolutely
  262. necessary (most of the time it isn't).
  263.  
  264.      It  is generally a good idea to compile without stack depth checking (-v in
  265. SAS) on.
  266.  
  267.      If  your  module  uses  the small data model, you should make sure that any
  268. functions  in  your  module  that get called by ImageFX (directly or indirectly)
  269. load  the  A4  register  to  point  to  your data base.  With SAS/C, you can use
  270. __saveds  for  all  such functions or take the lazy way out (like me :) and just
  271. compile  with  the  -y  flag.  I always do it the latter way so I'm not entirely
  272. sure  the  former  way  will work -- it should though. If you're really lazy you
  273. can just compile with -b0 and use the large data model.
  274.  
  275.      Modules  always  run  in  the ImageFX task context, using ImageFX's stack. 
  276. Modules do not have to be reentrant.
  277.  
  278.  
  279. 3.4. Types of Modules
  280.  
  281.      Well, on to the nitty-gritty details of the modules.
  282.  
  283.  
  284. 3.4.1. Loader Modules
  285.  
  286.      Loader  modules  convert  image  files  on  disk  into 8- or 24-bit buffers
  287. suitable  for  use  in  ImageFX.   They  are  also  used  for extracting palette
  288. information  from  files  (assuming  the  file  format  in  question  supports a
  289. palette).
  290.  
  291.      Generally  speaking,  each  Loader  module  will  handle  one file format. 
  292. However,  it  is  possible  to  allow  a single Loader to be able to read one of
  293. several  file  formats, or more commonly several variations of one file format. 
  294. This  is  done  by  passing  back an array of structures indicating the types of
  295. files  the loader can read.  Each file format must have its own unique ID number
  296. associated  with  it;  this ID value is passed to the module's load vector so it
  297. knows which format was matched.
  298.  
  299.      ImageFX  was  designed to automatically detect the file format of the image
  300. the  user  is  attempting  to  load,  so that he doesn't have to know what it is
  301. beforehand.   It  was  also  designed  to retain this ability no matter how many
  302. loader  modules  were added to the system.  In order for ImageFX to know what to
  303. look  for,  it  scans the modules/loaders/ directory (at startup time) and calls
  304. each  loader  module  in turn.  The loader module reports what "signature" bytes
  305. that  a  file  must  have in order to be considered as the file format that this
  306. loader  expects.   ImageFX  takes  this  information and stores it in a list and
  307. continues on to the next loader until all of them have been queried.
  308.  
  309.      When  the  user  asks  to load a file, ImageFX reads the first few bytes of
  310. the  file  and  compares  those  bytes  to  all  the entries in its list.  If it
  311. matches  one  of the entries, the approprate Loader module is loaded and control
  312. passes to it to read the image into memory.
  313.  
  314.      Another  method of file format detection exists.  If a file format does not
  315. have  any  "magic"  constants  at the beginning of the file, a Loader module may
  316.  
  317.  
  318.  
  319.  
  320. elect  to  do  "custom  file identification."  This means that ImageFX will call
  321. your  Loader  with the name of the file in question.  You loader module may then
  322. do  whatever  is  necessary  to  determine  whether  this  file is in the format
  323. expected  by  this module.  If it is not, ImageFX carries the search on to other
  324. loader  modules.   If  it  is,  control passes to your loader module to read the
  325. file  into  memory.   A  Loader module indicates that it wants to do custom file
  326. identification  by  returning  NULL in the function that would normally indicate
  327. what signature bytes to look for.
  328.  
  329.      ImageFX  also  provides  a  method  of automatically using a 68000 or 68030
  330. version  of a loader module.  The 68000 version of the loader module should have
  331. a  file  extension  of  ".000" and the 68030 version of the loader module should
  332. have  a file extension of ".030".  ImageFX will determine which loader module to
  333. use  based  on  the  CPU  in  the  current  system.   Loader modules without any
  334. extensions can be used on any system.
  335.  
  336.      There  are  four functions that you need to provide in your Loader module. 
  337. They   (in   order)   are   LM_Load(),  LM_LoadPalette(),  LM_Signatures(),  and
  338. LM_CheckFile().   For  detailed  information  about  these function, consult the
  339. loader module autodoc and the sample loader skeleton source code.
  340.  
  341.  
  342. 3.4.2. Saver Modules
  343.  
  344.      Saver  modules  are responsible for storing 8- or 24-bit image buffers onto
  345. disk  in  a  particular  file  format.   They also handle saving rendered (color
  346. mapped) images.
  347.  
  348.      Generally  speaking,  each  Saver  module  will  handle  one  file format. 
  349. However,  it  is  possible  to  allow  a single Saver to be able to write one of
  350. several  file  formats, or more commonly several variations of one file format. 
  351. This  is  done  by  passing  back an array of structures indicating the types of
  352. files  the saver can write.  Each file format must have its own unique ID number
  353. associated  with  it; this ID value is passed to the module's save vectors so it
  354. knows which format was matched.
  355.  
  356.      Similar    to    Loader    modules,    ImageFX   will   scan   the   entire
  357. modules/savers/directory  at  startup  time to record the names of all available
  358. save formats.
  359.  
  360.      When  the  user  chooses to save a file, he is presented with a list of all
  361. available  file  formats.   After  the  user selects one, ImageFX decides on the
  362. appropriate  Saver  module  to  call, and calls one of its save vectors to write
  363. the  file  to  disk (which vector depends on whether the user is saving a 24-bit
  364. file or a rendered image).
  365.  
  366.      Like  Loader modules, ImageFX also provides a method of automatically using
  367. a  68000  or  68030  version  of a saver module.  The 68000 version of the saver
  368. module  should  have  a  file  extension  of ".000" and the 68030 version of the
  369. saver  module  should  have  a file extension of ".030".  ImageFX will determine
  370. which  saver  module  to  use  based  on  the  CPU in the current system.  Saver
  371. modules without any extensions can be used on any system.
  372.  
  373.      There  are  four  functions that you need to provide in your Saver module. 
  374. They  (in  order)  are  SM_SaveTrue(),  SM_SaveMapped(),  SM_SavePalette(),  and
  375. SM_Signatures().   For  detailed  information about these functions, consult the
  376. saver module autodoc and the source code for the saver module skeleton.
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383. 3.4.3. Render Modules
  384.  
  385.      Render  modules are responsible for displaying 24-bit image data on various
  386. display  devices.   Generally  this  process  involves  quantizing (reducing the
  387. colors  in)  a 24-bit buffer down to some fewer number of colors (16 or 256, for
  388. example).   Render modules are not interactive, that is, they simple the display
  389. the  image  data.   The user may choose to save the rendered image from the Save
  390. gadget on the main menu.
  391.  
  392.      Render  modules  are  somewhat  more  complex  than  either Loader or Saver
  393. modules  because  of  the  introduction of a GUI.  The user must be able to have
  394. some  gadgets  to  click  on  when  he chooses your render module, even if it is
  395. nothing  more  than  a  "GO"  gadget.  Your render module should also follow the
  396. convention  of having a button in the upper left corner for changing the current
  397. module.
  398.  
  399.      ImageFX  uses  a  somewhat  unorthadox  method  of  creating GUIs, which is
  400. something  that  you'll  have  to  learn  to  create Render (as well as Scanner,
  401. Print,   and  Preview)  modules.   The  system  is  loosely  based  on  the  2.0
  402. gadTools.library,  but  goes  about  things  in a different way.  Basically, you
  403. hand  ImageFX  an  array  of  structures describing the GUI; each element of the
  404. array  describes a gadget, bevel box, image, or bit of text.  The gadgets in the
  405. list  may  be  given  functions  to  call  when they are "fiddled" with (buttons
  406. pressed,  sliders  slid, etc.).  ImageFX handles all of the event processing for
  407. you.   For further details of ImageFX's GUI system, refer to the Ged autodoc and
  408. "scan/ged.h".
  409.  
  410.      Render  modules  are  loaded  only when they are first accessed by the user
  411. (when  he first clicks on the Render gadget).  The module segment is then loaded
  412. into  memory,  and  the  standard  module  initialization  is performed.  Render
  413. modules  also  have  additional  initialization  steps  to  go  through  (the  functions
  414. RM_Init and RM_Show).
  415.  
  416.      <more to come - see example skeleton render module>
  417.  
  418.  
  419. 3.4.5. Printer Modules
  420.  
  421.      <more to come>
  422.  
  423.  
  424. 3.4.6. Preview Modules
  425.      <more to come - see example skeleton preview module>
  426.  
  427. 3.5. Language
  428.  
  429.      ImageFX  was  designed  as  an internationally-aware program.  All the text
  430. used  in the main program may be translated by the use of an external text file.
  431.  If  this  text file exists, ImageFX reads the text into an array in memory, and
  432. all  text  references  within  the program are made as indexes into this array. 
  433. Otherwise,   internal  (English)  defaults  are  used.   This  allows  for  easy
  434. translation of the program into other languages.
  435.  
  436.      ImageFX  also  provides  a  way  for  modules  to use the same technique of
  437. storing  text  in  an  external  text  file.  Modules should be designed to take
  438.  
  439.  
  440.  
  441.  
  442. advantage  of  this,  so  that they may be translated to other languages as well
  443. (remember that the majority of Amigas are in Europe).
  444.  
  445.      If you want your module to be internationally-aware, there are a couple
  446. things you need to do:
  447.  
  448.      In  your  module's  Open()  vector,  you  should fill in the "Language" and
  449. "LangCount"  fields  of  the  ModuleBase  structure.   ImageFX  will then try to
  450. locate  the  text  of  your module in a text file based on your language tag and
  451. return  a  pointer  to the resulting array of text strings in ModuleBase->Text. 
  452. If  the language text is found, you should get your text strings from this array
  453. only.
  454.  
  455.      The  standard  module  startup  code contains a helpful function for use in
  456. internationalizing  your  modules:   GetStr().  You should use this function for
  457. all your text references.  The format of the function call is as follows:
  458.  
  459.               char *text = GetStr (int index, char *default_text)
  460.  
  461.      This  function  will  examine  your  ModuleBase->Text  field  to  see if an
  462. external  text  file  was  successfully read.  If so, it will return the text at
  463. the  given  index  to  you.   If the text was not read in, then the default text
  464. string will be returned.
  465.  
  466.      The  name  of  the external text file depends on the type of module you are
  467. creating  and  the  language  tag  you specify in ModuleBase->Language.  ImageFX
  468. will  use a template like this:  "%ls_%ls.text", where the first argument is the
  469. *type*  of  module  (eg. Loader, Render, Saver, etc.) and the second argument is
  470. the  language  tag you specify.  For example, a scanner module with the language
  471. tag "Fuji" would reference the text file "Scanner_Fuji.text".
  472.  
  473.      A quick, fragmented example of a render module follows:
  474.  
  475.       /*******************************************************
  476.        * In the module, you should define your text as indexes
  477.        * into an array instead of as strings.  This is the
  478.        * index array:
  479.        */
  480.       enum {
  481.          TXT_Hello,
  482.          TXT_Goodbye,
  483.          TXT_Yikes,
  484.          TXT_COUNT         /* 3 entries */
  485.       };
  486.  
  487.       /*******************************************************
  488.        * In the module Open() vector, setup the ModuleBase
  489.        * Language and LangCount fields:
  490.        */
  491.       ModuleBase->Language = "MyModuleText";
  492.       ModuleBase->LangCount = TXT_COUNT;
  493.  
  494.       /*******************************************************
  495.        * Now whenever you want to use text, you reference it using
  496.        * the GetStr() function.
  497.        */
  498.       Errorf(GetStr(TXT_Yikes, "Yikes!"));
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.       ;********************************************************
  506.       ;* And in the ImageFX Text/ directory, you create a file
  507.       ;* called "Render_MyModuleText.text" with the following lines:
  508.       ;*
  509.       !MyModuleText
  510.       Hello
  511.       Goodbye
  512.       Yikes - an error!
  513.       #
  514.  
  515.  
  516. 3.6. Preferences
  517.  
  518.      <more to come>
  519.  
  520. 3.7. Modules and Arexx
  521.  
  522.      <more to come>
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.                                     4. HOOKS
  530.  
  531. 4.1. Theory
  532.  
  533.      ImageFX  Hooks  are  nothing  more  than executable programs.  When ImageFX
  534. launches  a  hook,  it  passes the name of the ImageFX function library to it as
  535. the  first  argument on the command line.  Once the hook program has opened this
  536. library,  it  can  access all of the functions in ImageFX, allowing it to get to
  537. the  image  buffers,  or  whatever.   Additional  command  line arguments may be
  538. passed if the hook invocation came from Arexx.
  539.  
  540.  
  541. 4.2. Hook Construction
  542.  
  543.      A  link-time startup module is provided to make building your hooks easier.
  544.  It  takes  care  of  all  the  "grunt" work of opening the function library and
  545. making  sure  everything  is  setup  properly.   In  addition, it copies certain
  546. library  pointers  (IntuitionBase  and  GfxBase)  into global variables for your
  547. immediate use.
  548.  
  549.      The  hook startup code calls the function "hook_main()" to invoke your hook
  550. code.  This is the only function you need to provide.
  551.  
  552.      There  are  also  three  global  variables you need to set so that the hook
  553. startup code knows what to do.  They are described below:
  554.  
  555.      HookName: (char *) The name of your hook program.
  556.  
  557.      HookText: (char *) Language tag to search for for this hook program (see
  558. "Language" below).
  559.  
  560.      HookTextCount: (int) Number of text entries to read for this hook program
  561. (see "Language" below).
  562.  
  563.      Failure to set these will probably result in a link error.
  564.  
  565.  
  566. 4.3. Language
  567.  
  568.      Hook programs may also be designed to take advantage of ImageFX's
  569. internationality.
  570.  
  571.      The  standard  hook  startup  code  contains  a helpful function for use in
  572. internationalizing  your  modules:   GetStr().  You should use this function for
  573. all your text references.  The format of the function call is as follows:
  574.  
  575.               char *text = GetStr (int index, char *default_text)
  576.  
  577.      This  function  will check to see if an external text file was successfully
  578. read.   If  so,  it will return to you the text at the given index.  If the text
  579. was not read in, then the default text string will be returned.
  580.  
  581.      A quick, fragmented example follows:
  582.  
  583.       /*******************************************************
  584.        * In the hook, you should define your text as indexes
  585.        * into an array instead of as strings.  This is the
  586.        * index array:
  587.  
  588.  
  589.  
  590.  
  591.        */
  592.       enum {
  593.          TXT_Hello,
  594.          TXT_Goodbye,
  595.          TXT_Yikes,
  596.          TXT_COUNT         /* 3 entries */
  597.       };
  598.  
  599.       /*******************************************************
  600.        * Use the following globals to tell the hook startup
  601.        * code what to look for:
  602.        */
  603.       HookText = "MyHookText";
  604.       HookTextCount = TXT_COUNT;
  605.  
  606.       /*******************************************************
  607.        * Now whenever you want to use text, you reference it using
  608.        * the GetStr() function.
  609.        */
  610.       Errorf(GetStr(TXT_Yikes, "Yikes!"));
  611.  
  612.  
  613.       ;********************************************************
  614.       ;* And in the ImageFX Text/ directory, you create a file
  615.       ;* called "Hook_MyHookText.text" with the following lines:
  616.       ;*
  617.       !MyHookText
  618.       Hello
  619.       Goodbye
  620.       Yikes - an error!
  621.       #
  622.  
  623.  
  624. 4.4. Hooks and Arexx
  625.  
  626.      When  a  hook  is  invoked via. Arexx, arguments may be passed to your hook
  627. code via. the command line.
  628.  
  629.      The  hook_main()  function  has  two  arguments just like a standard main()
  630. function;  'argc'  and  'argv'.   You can use these to peruse any arguments that
  631. were sent to your hook program via. Arexx.
  632.  
  633.      For example, suppose the user issued the command:
  634.  
  635.                           "Hook YourHook 1 4 Cookies"
  636.  
  637.      Your hook_main() function will get the following:
  638.  
  639.           argc = 4
  640.           argv[0] = <ignored>
  641.           argv[1] = "1"
  642.           argv[2] = "4"
  643.           argv[3] = "Cookies"
  644.  
  645.      Why  is  the first one ignored?  To keep the same conventions as standard C
  646. main() functions.
  647.  
  648.      If  you  need  to  get  to  the RexxMsg that invoked your hook program (for
  649.  
  650.  
  651.  
  652.  
  653. example,  to  setup  result strings or set variables), you can look in the field
  654. ScanBase->sb_HookMsg.   If this field is NULL, then your hook was not invoked by
  655. Arexx  (ie.  the  user  could  have just typed something in the command shell). 
  656. Otherwise,  it  points  to  a  RexxMsg  structure which you can use for whatever
  657. purpose.
  658.  
  659.      A  handy function contained in ScanBase is called SetResult().  It lets you
  660. set  the  result string to return to an Arexx program in a fairly easy fashion. 
  661. It's prototype is:
  662.  
  663.              BOOL SetResult (struct RexxMsg *msg, char *fmt, ...);
  664.  
  665.      The  result  string  to  pass back to the Arexx program associated with the
  666. given  RexxMsg  will  be  set  to the formatted string passed in.  It is safe to
  667. pass a NULL for the RexxMsg, in which case nothing is done.
  668.  
  669.  
  670.